﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Jermaine
{
    /// <summary>
    /// 实例
    /// </summary>
    public class ObjectFactory
    {
        private static readonly Dictionary<string, Object> storage;
        private static readonly Dictionary<string, Object> instances;
        private static readonly object storageSyncRoot;
        private static readonly object instanceSyncRoot;

        static ObjectFactory() {
            storage = new Dictionary<string, Object>();
            instances = new Dictionary<string, object>();
            storageSyncRoot = ((ICollection)storage).SyncRoot;
            instanceSyncRoot = ((ICollection)instances).SyncRoot;
        }

        private ObjectFactory() { }

        /// <summary>
        /// 添加
        /// </summary>
        /// <typeparam name="TInstance"></typeparam>
        /// <param name="o"></param>
        public static void Put<TInstance>(TInstance o) {
            var type = typeof(TInstance);
            var name = type.FullName;

            try {
                lock (storageSyncRoot) {
                    if (storage.ContainsKey(name)) {
                        storage[name] = o;
                    } else {
                        storage.Add(name, o);
                    }
                }
            } catch { }
        }

        /// <summary>
        /// 添加
        /// </summary>
        /// <typeparam name="TInstance"></typeparam>
        /// <param name="key"></param>
        /// <param name="o"></param>
        public static void Put<TInstance>(string key, TInstance o) {
            Object value;
            var type = typeof(TInstance);
            var name = type.FullName;
            lock (instanceSyncRoot) {
                if (!instances.TryGetValue(name, out value)) {
                    value = new Storage<TInstance>();
                    instances.Add(name, value);
                }
            }
            (value as Storage<TInstance>).Put(key, o);
        }

        /// <summary>
        /// 获取
        /// </summary>
        /// <typeparam name="TInstance"></typeparam>
        /// <returns></returns>
        public static TInstance Get<TInstance>() {
            var type = typeof(TInstance);
            var name = type.FullName;
            TInstance o = default(TInstance);

            try {
                lock (storageSyncRoot) {
                    if (storage.ContainsKey(name)) {
                        o = (TInstance)storage[name];
                    } else {
                        o = Activator.CreateInstance<TInstance>();
                        storage.Add(name, o);
                    }
                }
            } catch { }
            return o;
        }

        /// <summary>
        /// 获取
        /// </summary>
        /// <typeparam name="TInstance"></typeparam>
        /// <param name="key"></param>
        /// <returns></returns>
        public static TInstance Get<TInstance>(string key) {
            Object o;
            var type = typeof(TInstance);
            var name = type.FullName;
            lock (instanceSyncRoot) {
                if (!instances.TryGetValue(name, out o)) {
                    o = new Storage<TInstance>();
                    instances.Add(name, o);
                }
            }
            return (o as Storage<TInstance>).Get(key);
        }

        /// <summary>
        /// 移除
        /// </summary>
        /// <typeparam name="TInstance"></typeparam>
        public static void Remove<TInstance>() {
            var type = typeof(TInstance);
            var name = type.FullName;

            try {
                lock (storageSyncRoot) {
                    if (storage.ContainsKey(name)) {
                        storage.Remove(name);
                    }
                }
            } catch { }

        }

        /// <summary>
        /// 移除
        /// </summary>
        /// <typeparam name="TInstance"></typeparam>
        /// <param name="key"></param>
        public static void Remove<TInstance>(string key) {
            Object o;
            var type = typeof(TInstance);
            var name = type.FullName;
            lock (instanceSyncRoot) {
                instances.TryGetValue(name, out o);
            }
            if (o != null) {
                (o as Storage<TInstance>).Remove(key);
            }
        }

        /// <summary>
        /// 存在
        /// </summary>
        /// <typeparam name="TInstance"></typeparam>
        /// <returns></returns>
        public static bool Exists<TInstance>() {
            var type = typeof(TInstance);
            var name = type.FullName;
            try {
                lock (storageSyncRoot) {
                    return storage.ContainsKey(name);
                }
            } catch { }
            return false;
        }
        /// <summary>
        /// 存在
        /// </summary>
        /// <typeparam name="TInstance"></typeparam>
        /// <param name="key"></param>
        /// <returns></returns>
        public static bool Exists<TInstance>(string key) {
            Object o;
            var type = typeof(TInstance);
            var name = type.FullName;
            lock (instanceSyncRoot) {
                instances.TryGetValue(name, out o);
            }
            if (o != null) {
                return (o as Storage<TInstance>).Exists(key);
            }

            return false;
        }

        class Storage<TInstance>
        {
            private readonly Dictionary<string, TInstance> storage;

            private object syncRoot;

            public Storage() {
                storage = new Dictionary<string, TInstance>();
                syncRoot = (storage as ICollection).SyncRoot;
            }

            /// <summary>
            /// 添加
            /// </summary>
            /// <param name="key"></param>
            /// <returns></returns>
            public TInstance Get(string key) {
                TInstance o = default(TInstance);
                try {
                    lock (syncRoot) {

                        if (!this.storage.TryGetValue(key, out o)) {
                            o = Activator.CreateInstance<TInstance>();
                            this.storage.Add(key, o);
                        }

                    }
                } catch {

                }
                return o;
            }

            /// <summary>
            /// 获取
            /// </summary>
            /// <param name="key"></param>
            /// <param name="o"></param>
            public void Put(String key, TInstance o) {
                try {
                    lock (syncRoot) {
                        if (!this.storage.ContainsKey(key)) {
                            this.storage.Add(key, o);
                        } else {
                            this.storage[key] = o;
                        }
                    }
                } catch {

                }
            }
            /// <summary>
            /// 移除
            /// </summary>
            /// <param name="key"></param>
            public void Remove(String key) {
                try {
                    lock (syncRoot) {
                        if (this.storage.ContainsKey(key)) {
                            this.storage.Remove(key);
                        }
                    }
                } catch {

                }
            }
            /// <summary>
            /// 存在
            /// </summary>
            /// <param name="key"></param>
            /// <returns></returns>
            public bool Exists(string key) {
                try {
                    lock (syncRoot) {
                        return this.storage.ContainsKey(key);
                    }
                } catch {

                }
                return false;
            }
        }
    }


}
